package com.geoai.uimap.core.mapbox

import com.mapbox.mapboxsdk.camera.CameraPosition
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
import com.mapbox.mapboxsdk.geometry.LatLng
import com.mapbox.mapboxsdk.geometry.LatLngBounds
import com.mapbox.mapboxsdk.maps.MapboxMap
import com.geoai.uimap.api.IGEOMapCamera
import com.geoai.uimap.core.geomap.bean.GEOMapCameraPosition
import com.geoai.uimap.geo.ILatLng
import com.geoai.uimap.model.GEOLatLng
import com.geoai.uimap.utils.toGEOLatLng

class MapboxCamera(private val map: MapboxImpl) : IGEOMapCamera {
    override fun getPosition(): GEOLatLng {
        val center = getMapbox().cameraPosition.target
        return GEOLatLng(center.latitude, center.longitude)
    }

    override fun setPosition(position: ILatLng) {
        val target = CameraPosition.Builder()
                .target(LatLng(position.latitude, position.longitude))
                .build()
        getMapbox().animateCamera(CameraUpdateFactory.newCameraPosition(target))
    }


    override fun setPosition(position: ILatLng, level: Float, padding: DoubleArray?) {
        val target = CameraPosition.Builder()
                .target(LatLng(position.latitude, position.longitude))
                .zoom(level.toDouble())
            .padding(padding)
                .build()
        getMapbox().animateCamera(CameraUpdateFactory.newCameraPosition(target))
    }

    override fun changeBearing(bearValue: Float) {
        val target = CameraPosition.Builder()
                .bearing(bearValue.toDouble())
                .build()
        getMapbox().animateCamera(CameraUpdateFactory.newCameraPosition(target))
    }

    override fun getCameraPosition(): GEOMapCameraPosition? {
        val cameraP = getMapbox().cameraPosition
        val newCameraPosition = GEOMapCameraPosition()
        newCameraPosition.zoom = cameraP.zoom.toFloat()
        newCameraPosition.bearing = cameraP.bearing.toFloat()
        newCameraPosition.target = cameraP.target.toGEOLatLng()
        newCameraPosition.padding = cameraP.padding
        return newCameraPosition
    }

    override fun getCameraPadding(): DoubleArray? {
        return getMapbox().cameraPosition.padding
    }

    override fun getZoomLevel(): Double {
        return getMapbox().cameraPosition.zoom
    }

    override fun setZoomLevel(level: Double) {
        getMapbox().animateCamera(
                CameraUpdateFactory
                        .zoomTo(level)
        )
    }

    override fun zoomToBounds(bound: List<ILatLng>, padding: Int) {
        val bounds =
                LatLngBounds.Builder().includes(bound.map { LatLng(it.latitude, it.longitude) }).build()
        getMapbox().animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, padding))
    }

    override fun zoomToBounds(bound: List<ILatLng>, paddingHLeft: Int, paddingVTop: Int, paddingHRight: Int, paddingVBottom: Int) {
        val bounds =
            LatLngBounds.Builder().includes(bound.map { LatLng(it.latitude, it.longitude) }).build()
        getMapbox().animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, paddingHLeft, paddingVTop, paddingHRight, paddingVBottom))
    }

    override fun getMaxZoomLevel(): Double {
        return getMapbox().maxZoomLevel
    }

    override fun getMinZoomLevel(): Double {
        return getMapbox().minZoomLevel
    }

    override fun zoomIn() {
        getMapbox().animateCamera(CameraUpdateFactory.zoomIn())
    }

    override fun zoomOut() {
        getMapbox().animateCamera(CameraUpdateFactory.zoomOut())
    }

    override fun zoomTo(zoom: Double) {
        getMapbox().animateCamera(CameraUpdateFactory.zoomTo(zoom))
    }

    private fun getMapbox(): MapboxMap {
        return map.getMapbox()!!
    }
}